import ioc.bean.Dog;
import ioc.config.BeanLifeCycleConfig;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * <pre>
 * bean 的生命周期：创建---初始化---销毁
 * 容器管理 bean 的生命周期：我们可以自定义初始化和销毁方法；容器在 bean 进行到当前生命周期的时候来调用我们自定义的初始化和销毁方法；
 * =============================================================================
 * 构造（对象创建）：
 * 		单实例：在容器启动的时候创建对象；
 * 		多实例：在每次获取的时候创建对象；
 *
 * =》BeanPostProcessor.postProcessBeforeInitialization
 *
 * 初始化：
 * 		对象创建完成，并赋值好，调用初始化方法。。。
 *
 * =》BeanPostProcessor.postProcessAfterInitialization
 *
 * 销毁：
 * 		单实例：容器关闭的时候调用销毁方法；
 * 		多实例：容器不会管理这个 bean，容器关闭时也不会调用销毁方法；
 * =============================================================================
 * 1）、指定初始化和销毁方法；
 * 		通过 @Bean 指定 init-method 和 destroy-method；
 * 2）、通过让 Bean 实现 InitializingBean（定义初始化逻辑），
 * 				DisposableBean（定义销毁逻辑）;
 * 3）、可以使用JSR250；
 *      @PostConstruct：在 bean 创建完成并且属性赋值完成；来执行初始化方法
 *      @PreDestroy：在容器销毁 bean 之前通知我们进行清理工作
 * 4）、BeanPostProcessor【interface】：bean 的后置处理器；
 * 		在 bean 初始化前后进行一些处理工作；
 * 		postProcessBeforeInitialization:在初始化之前工作
 * 		postProcessAfterInitialization:在初始化之后工作
 * </pre>
 */
public class T02_BeanLifeCycle {
    ConfigurableApplicationContext context;

    @Test
    public void lifeCycle() {
        context = new AnnotationConfigApplicationContext(BeanLifeCycleConfig.class);
        context.getBean("car");
    }

    @Test
    public void ann() {
        context = new AnnotationConfigApplicationContext(BeanLifeCycleConfig.class);
        context.getBean(Dog.class);
    }

    @Test
    public void xml() {
        context = new ClassPathXmlApplicationContext("BeanLifeCycle.xml");
    }

    @AfterEach
    public void printBeans() {
        System.out.println("============容器中的对象==========");
        String[] definitionNames = context.getBeanDefinitionNames();
        for (String name : definitionNames) {
            System.out.println(name);
        }
        System.out.println("=================================");
        context.close(); // 关闭容器
    }
}
